#include "ff_tts_win_plugin.h"

// This must be included before many other Windows headers.
#include <windows.h>

// For getPlatformVersion; remove unless needed for your plugin implementation.
#include <VersionHelpers.h>

#include <flutter/method_channel.h>
#include <flutter/plugin_registrar_windows.h>
#include <flutter/standard_method_codec.h>

#include <map>
#include <memory>
#include <sstream>

using namespace std;

namespace ff_tts_win {

	// static
	void FfTtsWinPlugin::RegisterWithRegistrar(
		flutter::PluginRegistrarWindows* registrar) {
		auto channel =
			std::make_unique<flutter::MethodChannel<flutter::EncodableValue>>(
				registrar->messenger(), "ff_tts_win",
				&flutter::StandardMethodCodec::GetInstance());

		auto plugin = std::make_unique<FfTtsWinPlugin>();

		channel->SetMethodCallHandler(
			[plugin_pointer = plugin.get()](const auto& call, auto result) {
			plugin_pointer->HandleMethodCall(call, std::move(result));
		});

		registrar->AddPlugin(std::move(plugin));
	}

	FfTtsWinPlugin::FfTtsWinPlugin() {}

	FfTtsWinPlugin::~FfTtsWinPlugin() {}

	void FfTtsWinPlugin::HandleMethodCall(
		const flutter::MethodCall<flutter::EncodableValue>& method_call,
		std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result) {
		cout << method_call.method_name() << endl;
		if (method_call.method_name().compare("getPlatformVersion") == 0) {
			std::ostringstream version_stream;
			version_stream << "Windows ";
			if (IsWindows10OrGreater()) {
				version_stream << "10+";
			}
			else if (IsWindows8OrGreater()) {
				version_stream << "8";
			}
			else if (IsWindows7OrGreater()) {
				version_stream << "7";
			}
			result->Success(flutter::EncodableValue(version_stream.str()));
		}
		else if (method_call.method_name().compare("init") == 0) {
			bool b = tts.Init();
			result->Success(flutter::EncodableValue(b));
		}
		else if (method_call.method_name().compare("dispose") == 0) {
			tts.Dispose();
			result->Success(flutter::EncodableValue(true));
		}
		else if (method_call.method_name().compare("rate") == 0) {
			int rate = 0;
			const auto* arguments = std::get_if<flutter::EncodableMap>(method_call.arguments());
			if (arguments) {
				auto rate_it = arguments->find(flutter::EncodableValue("rate"));
				if (rate_it != arguments->end()) {
					rate = std::get<int>(rate_it->second);
				}
			}
			cout << "rate=" << rate << endl;
			bool b = tts.Rate(rate);
			result->Success(flutter::EncodableValue(b));
		}
		else if (method_call.method_name().compare("speak") == 0) {
			std::string text;
			const auto* arguments = std::get_if<flutter::EncodableMap>(method_call.arguments());
			if (arguments) {
				auto text_it = arguments->find(flutter::EncodableValue("text"));
				if (text_it != arguments->end()) {
					text = std::get<std::string>(text_it->second);
				}
			}
			if (text.empty()) {
				result->Success(flutter::EncodableValue(false));
				return;
			}
			cout << text << endl;
			bool b = tts.Speak(text);
			result->Success(flutter::EncodableValue(b));
		}
		else {
			result->NotImplemented();
		}
	}

}  // namespace ff_tts_win
